﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Architecture.ComponentLogic.ElementModel;

namespace AddIn.EA.Architecture.ComponentLogic.StandardProject.Builders.Service
{
    public class ElementBuilderServiceContractImplementation : ElementBuilder
    {
        public override void BuildStructure(ComponentLogic.ElementModel.Package viewModel, Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            BuildServiceContractElement(viewModel, templateRepository, itemEntity);
            BuildServiceImplementationElement(viewModel, templateRepository, itemEntity);
            BuildTranslatorBusinessEntityToDataContractElement(viewModel, templateRepository, itemEntity);
            BuildTranslatorDataContractToBusinessEntityElement(viewModel, templateRepository, itemEntity);
        }
        public void BuildServiceContractElement(ComponentLogic.ElementModel.Package viewModel, Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            AddIn.EA.Framework.Element templateServiceContractElement = GetTemplateServiceContractElement(templateRepository);

            ComponentLogic.ElementModel.Package serviceContractPackage = GetServiceContractPackage(viewModel);

            String elementNameServiceContract = templateServiceContractElement.Name.Replace("[entity_name]", itemEntity.Name);

            serviceContractPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementNameServiceContract) == 0);
            //Build ServiceContract Element.
            Element serviceContractElement = BuildEntityElementFromTemplate(itemEntity, templateServiceContractElement, elementNameServiceContract);
            serviceContractElement.Type = ElementType.Interface;

            BindElementMethods(serviceContractElement, itemEntity, "DataContract.Request", "DataContract.Response");

            //Including elements in the package
            serviceContractPackage.Elements.Add(serviceContractElement);
        }
        public void BuildServiceImplementationElement(ComponentLogic.ElementModel.Package viewModel, Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            AddIn.EA.Framework.Package templatePackageServiceImplementation = GetTemplatePackageServiceImplementation(templateRepository);
            AddIn.EA.Framework.Element templateServiceImplementationElement = templatePackageServiceImplementation.GetElementByName("[entity_name]");
            AddIn.EA.Framework.Element templateServiceContractElement = GetTemplateServiceContractElement(templateRepository);

            ComponentLogic.ElementModel.Package serviceImplementationPackage = GetServiceImplementationPackage(viewModel);

            String elementNameServiceImplementation = templateServiceImplementationElement.Name.Replace("[entity_name]", itemEntity.Name);

            serviceImplementationPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementNameServiceImplementation) == 0);

            //Build ServiceImplementation Element.
            Element serviceImplementationElement = BuildEntityElementFromTemplate(itemEntity, templateServiceImplementationElement, elementNameServiceImplementation);
            serviceImplementationElement.InheritanceClassName = templateServiceContractElement.Name.Replace("[entity_name]", itemEntity.Name);

            BindElementMethods(serviceImplementationElement, itemEntity, "DataContract.Request", "DataContract.Response");

            //Including elements in the package
            serviceImplementationPackage.Elements.Add(serviceImplementationElement);
        }
        public void BuildTranslatorBusinessEntityToDataContractElement(ComponentLogic.ElementModel.Package viewModel, Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            AddIn.EA.Framework.Package templatePackageTranslator = GetTemplatePackageTranslatorBusinessEntityToDataContract(templateRepository);
            AddIn.EA.Framework.Element templateTranslatorElement = templatePackageTranslator.GetElementByName("[entity_name]");
            ComponentLogic.ElementModel.Package translatorPackage = GetTranslatorBusinessEntityToDataContractPackage(viewModel);
            

            String elementNameTranslator = templateTranslatorElement.Name.Replace("[entity_name]", itemEntity.Name);

            translatorPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementNameTranslator) == 0);

            //Build ServiceImplementation Element.
            Element translatorElement = BuildEntityElementFromTemplate(itemEntity, templateTranslatorElement, elementNameTranslator);

            //Including elements in the package
            translatorPackage.Elements.Add(translatorElement);
        }

        public void BuildTranslatorDataContractToBusinessEntityElement(ComponentLogic.ElementModel.Package viewModel, Framework.RepositoryManager templateRepository, BusinessEntityStandardProject itemEntity)
        {
            AddIn.EA.Framework.Package templatePackageTranslator = GetTemplatePackageTranslatorDataContractToBusinessEntity(templateRepository);
            AddIn.EA.Framework.Element templateTranslatorElement = templatePackageTranslator.GetElementByName("[entity_name]");
            ComponentLogic.ElementModel.Package translatorPackage = GetTranslatorDataContractToBusinessEntityPackage(viewModel);


            String elementNameTranslator = templateTranslatorElement.Name.Replace("[entity_name]", itemEntity.Name);

            translatorPackage.Elements.RemoveAll(it => it.Name.CompareTo(elementNameTranslator) == 0);

            //Build ServiceImplementation Element.
            Element translatorElement = BuildEntityElementFromTemplate(itemEntity, templateTranslatorElement, elementNameTranslator);

            //Including elements in the package
            translatorPackage.Elements.Add(translatorElement);
        }

        protected override Method CreateElementModelMethod(MethodStandardProject itemMethod, string namespaceParameters, string namespaceReturn)
        {
            Method method = base.CreateElementModelMethod(itemMethod, namespaceParameters, namespaceReturn);
            //TODO: Efetuar a correção do posfixo nos parâmetros dos métodos pois deve-se referenciar o objeto "Request" e/ou "Response".
            return method;
        }
        private Framework.Package GetTemplatePackageServiceContract(Framework.RepositoryManager templateRepository)
        {
            return templateRepository.GetPackageByName("Servico").GetPackageByName("Service").GetPackageByName("ServiceContract");
        }
        private Framework.Package GetTemplatePackageServiceImplementation(Framework.RepositoryManager templateRepository)
        {
            return templateRepository.GetPackageByName("Servico").GetPackageByName("Service").GetPackageByName("ServiceImplementation");
        }
        private Framework.Package GetTemplatePackageTranslatorBusinessEntityToDataContract(Framework.RepositoryManager templateRepository)
        {
            return templateRepository.GetPackageByName("Servico").GetPackageByName("Service").GetPackageByName("ServiceImplementation").GetPackageByName("Translator").GetPackageByName("BusinessEntityToDataContract");
        }

        private Framework.Package GetTemplatePackageTranslatorDataContractToBusinessEntity(Framework.RepositoryManager templateRepository)
        {
            return templateRepository.GetPackageByName("Servico").GetPackageByName("Service").GetPackageByName("ServiceImplementation").GetPackageByName("Translator").GetPackageByName("DataContractToBusinessEntity");
        }

        private Framework.Element GetTemplateServiceContractElement(Framework.RepositoryManager templateRepository)
        {
            return GetTemplatePackageServiceContract(templateRepository).GetElementByName("I[entity_name]");
        }
        private Package GetServicePackage(ComponentLogic.ElementModel.Package viewModel)
        {
            ComponentLogic.ElementModel.Package servicoPackage = GetViewModelPackage("Servico", viewModel, true);
            ComponentLogic.ElementModel.Package servicePackage = GetViewModelPackage("Service", servicoPackage, true);
            return servicePackage;
        }
        private Package GetServiceContractPackage(ComponentLogic.ElementModel.Package viewModel)
        {
            ComponentLogic.ElementModel.Package servicePackage = GetServicePackage(viewModel);
            ComponentLogic.ElementModel.Package serviceContractPackage = GetViewModelPackage("ServiceContract", servicePackage, true);
            return serviceContractPackage;
        }
        private Package GetServiceImplementationPackage(ComponentLogic.ElementModel.Package viewModel)
        {
            ComponentLogic.ElementModel.Package servicePackage = GetServicePackage(viewModel);
            ComponentLogic.ElementModel.Package serviceImplementationPackage = GetViewModelPackage("ServiceImplementation", servicePackage, true);
            return serviceImplementationPackage;
        }
        private Package GetTranslatorBusinessEntityToDataContractPackage(ComponentLogic.ElementModel.Package viewModel)
        {
            ComponentLogic.ElementModel.Package servicePackage = GetServicePackage(viewModel);
            ComponentLogic.ElementModel.Package serviceImplementationPackage = GetViewModelPackage("ServiceImplementation", servicePackage, true);
            ComponentLogic.ElementModel.Package translatorPackage = GetViewModelPackage("Translator", serviceImplementationPackage, true);
            ComponentLogic.ElementModel.Package translatorBusinessEntityToDataContractPackage = GetViewModelPackage("BusinessEntityToDataContract", translatorPackage, true);
            return translatorBusinessEntityToDataContractPackage;
        }

        private Package GetTranslatorDataContractToBusinessEntityPackage(ComponentLogic.ElementModel.Package viewModel)
        {
            ComponentLogic.ElementModel.Package servicePackage = GetServicePackage(viewModel);
            ComponentLogic.ElementModel.Package serviceImplementationPackage = GetViewModelPackage("ServiceImplementation", servicePackage, true);
            ComponentLogic.ElementModel.Package translatorPackage = GetViewModelPackage("Translator", serviceImplementationPackage, true);
            ComponentLogic.ElementModel.Package translatorDataContractToBusinessEntityPackage = GetViewModelPackage("DataContractToBusinessEntity", translatorPackage, true);
            return translatorDataContractToBusinessEntityPackage;
        }

        public override void Validate()
        {
        }
    }
}
